#include "scan.h"
#include "limits.h"
#include "global.h"
#include "math.h"
#include <papi.h>
pthread_mutex_t lock;
pthread_barrier_t barrier;

class Prefix: public Scanner<double, double>
{
public:
  double init() { return 0.0;}
  double accum(double t, double d) { 
	if(t<d)
		return d;
	else
		return t;
  }
  double combine(double left, double right) {
	if(left<right)
		return right;
	else
		return left;
  }
  double scan(double t, double s) { 
	if(s>=t)
		return 1.0;
	else
		return -1.0;
  }
  Prefix(double* data, double* result, INDEX length)
    : Scanner<double, double>(data, result, length) {}
};

int main() {
  double* data = (double*) new double [INPUT_SIZE];
  double* result = (double*) new double [INPUT_SIZE];
  double* result2= (double*) new double [INPUT_SIZE];  
  // initialize PAPI library
  unsigned long chkflg = PAPI_VER_CURRENT;
  PAPI_library_init(chkflg);
  if (chkflg != PAPI_VER_CURRENT) {
    cout<<"Error PAPI Library out of date"<<endl;
    exit(1);
  }

  // generate the input
  srand(time(NULL));
  for(INDEX i=0; i<INPUT_SIZE; i++)
    data[i] = (rand()%INPUT_RANGE)/(i+1.0);

  // start timing
  long long start = PAPI_get_real_usec();

  //start
  Prefix prefix(data, result, INPUT_SIZE);
  prefix.Start();

  // end timing
  long long end = PAPI_get_real_usec();
  
  // check result
  double ht=0;
  for(INDEX i=0; i<INPUT_SIZE; i++) {
        //cout<<data[i]<<result[i]<<endl;
	if(data[i]>=ht){
		ht=data[i];
		result2[i]=1.0;
		assert(result[i]==result2[i]);
	}else{
		result2[i]=-1.0;
		assert(result[i]==result2[i]);
	}
  }
  cout<<endl<<"Succeeded"<<endl;

  // timing2
  long long end2 = PAPI_get_real_usec();

  cout<<"time in us"<<endl<<"p "<<end-start<<endl<<"s "<<end2-end<<endl;
  cout<<"size "<<INPUT_SIZE<<"threads "<<P<<endl;
  pthread_exit(NULL);
}
